package com.grace.storage.service.impl;

import java.io.IOException;
import java.util.Map;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.persistent.FileRecorder;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.grace.common.enums.GraceServerRoot;
import com.grace.common.enums.GraceStorageRoot;
import com.grace.common.exception.file.FileSizeLimitExceededException;
import com.grace.common.exception.file.InvalidExtensionException;
import com.grace.common.utils.StringUtils;
import com.grace.common.utils.file.FileUploadUtils;
import com.grace.common.utils.file.MimeTypeUtils;
import com.grace.storage.domain.SysStorage;
import com.grace.storage.enums.StorageEnum;
import com.grace.storage.enums.PrefixTypeEnums;
import com.grace.storage.enums.properties.StorageConfigProperties;
import com.grace.storage.enums.properties.QnYunProperties;
import com.grace.storage.mapper.SysStorageMapper;
import com.grace.storage.service.StorageHandler;
import com.grace.storage.utils.StorageUtils;
import com.grace.system.service.impl.SysSearchConfigServiceImpl;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class QiNiuStorageHander implements StorageHandler {
    private static final Logger log = LoggerFactory.getLogger(StorageHandler.class);
    @Autowired
    private SysSearchConfigServiceImpl configService;

    @Autowired
    private SysStorageMapper storageMapper;

    @Override
    public SysStorage storageUpload(MultipartFile file, GraceStorageRoot serverRoot)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {

        FileUploadUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);

        SysStorage data = new SysStorage();
        String fileName = FilenameUtils.getName(file.getOriginalFilename());
        // 二级目录
        String fileType = StorageUtils.getFileTypeExtension(FileUploadUtils.getExtension(file));
        // 获取配置文件
        Map<String, String> mp = getQiNiuConfig();
        Configuration cfg = new Configuration(getQnYunZone(mp.get(QnYunProperties.STORAGE_ZONE.getValue())));
        String bucket = mp.get(QnYunProperties.STORAGE_BUCKET.getValue());
        Auth auth = getAuth(mp);
        StringMap putPolicy = new StringMap();
        putPolicy.put("returnBody",
                "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
        long expireSeconds = 3600;
        String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
        String localTempDir = GraceStorageRoot.TMP_DIR.getWorkRoot(bucket);
        try { // 设置断点续传文件进度保存目录
            FileRecorder fileRecorder = new FileRecorder(localTempDir);
            UploadManager uploadManager = new UploadManager(cfg, fileRecorder);
            // 构造文件key
            String fk = StorageHandler.getKey(fileType, file, Boolean.parseBoolean(
                    configService.selectConfigDefaultValue(StorageConfigProperties.STORAGE_CONFIG_GROUP.defaultValue(),
                            StorageConfigProperties.STORAGE_FILE_NAME_ZH_PY)),PrefixTypeEnums.TIMEYMD);
            Response response = uploadManager.put(file.getInputStream(), StorageHandler.pathToUrl(fk), upToken, null, null);
            // 获取回调
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            data.setFk(putRet.key);
            data.setFileName(FilenameUtils.getName(file.getOriginalFilename()));
            data.setFileType(fileType);
            data.setSize(file.getSize());
            data.setDomain(mp.get(QnYunProperties.STORAGE_DOMAIN.getValue()));
            data.setFileName(fileName);
            data.setStorageType(getStorageType());
            storageMapper.insertSysStorage(data);

        } catch (QiniuException e) {
            log.error(e.getMessage());
        }
        return data;

    }

    @Override
    public void storageDelete(String key) {
        Map<String, String> mp = getQiNiuConfig();
        Configuration cfg = new Configuration(getQnYunZone(mp.get(QnYunProperties.STORAGE_ZONE.getValue())));
        // ...其他参数参考类注释
        String bucket = mp.get(QnYunProperties.STORAGE_BUCKET.getValue());

        try {
            Auth auth = getAuth(mp);
            BucketManager bucketManager = new BucketManager(auth, cfg);
            bucketManager.delete(bucket, key.replace("\\", "/"));

        } catch (QiniuException e) {
            log.error(e.getMessage());
        }

    }

    private Map<String, String> getQiNiuConfig() {

        return configService.selectConfigValueMapByGroupName(StorageConfigProperties.STORAGE_CONFIG_GROUP.getValue());
    }

    private Auth getAuth(Map<String, String> mp) throws QiniuException {
        String accessKey = mp.get(QnYunProperties.STORAGE_ACCESS_KEY.getValue());
        String secretKey = mp.get(QnYunProperties.STORAGE_SECRET_KEY.getValue());
        String bucket = mp.get(QnYunProperties.STORAGE_BUCKET.getValue());
        String zone = mp.get(QnYunProperties.STORAGE_ZONE.getValue());
        if (StringUtils.isAnyBlank(accessKey, secretKey, bucket, zone)) {
            throw new QiniuException(null, "请先七牛配置");
        }
        Auth auth = Auth.create(accessKey, secretKey);
        return auth;
    }

    private Zone getQnYunZone(String z) {
        Zone zone;
        switch (z) {
            case "z0":
                zone = Zone.zone0();
                break;
            case "z1":
                zone = Zone.zone1();
                break;
            case "z2":
                zone = Zone.zone2();
                break;
            case "na0":
                zone = Zone.zoneNa0();
                break;
            case "as0":
                zone = Zone.zoneAs0();
                break;
            default:
                // Default is detecting zone automatically
                zone = Zone.autoZone();
        }
        return zone;
    }

    @Override
    public String getStorageType() {

        return StorageEnum.STORAGE_TYPE_QN.getValue();
    }

    @Override
    public SysStorage storageAppoint(MultipartFile file, GraceStorageRoot rootPath,
            String[] allowedExtensio, PrefixTypeEnums prefixTypeEnums, boolean chan)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'storageAppoint'");
    }

    @Override
    public SysStorage storageAppointUpload(MultipartFile file, GraceServerRoot rootPath, String fileName,
            String[] allowedExtensio, PrefixTypeEnums prefixTypeEnums, boolean chan)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'storageAppointUpload'");
    }

    @Override
    public SysStorage storageAppointUpload(MultipartFile file, GraceServerRoot rootPath, String[] allowedExtensio,
            PrefixTypeEnums prefixTypeEnums, boolean chan)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("Unimplemented method 'storageAppointUpload'");
    }

 

  

  

 



   

   

}
